#!/usr/bin/env python
# -*- coding: utf-8 -*-

# dracdumper.py is a simple program to gather information from
# Dell Remote Access Controller (DRAC).

# Copyright (C) 2012 Jorge Rúa Riveiro <jruariveiro@gmail.com>

# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the
# Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the
# Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice
# shall be included in all copies or substantial portions of
# the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# drac = {'10.10.10.10': {'ip': '192.168.1.1', 'mac' : '00:a0:bc:11:a2', 'firmware' : '1.44' }, '10.10.10.11': {'ip': '192.168.1.2', 'mac' : '01:a0:bc:11:a2', 'firmware' : '1.43' } }

# TODO LIST

# Prompt for password (getpassword)
# Refactor get_dracinfo printing
# Logging
# UI 

import argparse
import socket
import re
import sys
import datetime
import os

try:
    import paramiko
except ImportError:
    sys.exit("You need python-paramiko package in order to run this program! Aborting.")

# Request codes

FIRMWARE_VERSION    = 0
IP_ADDRESS          = 1
MAC_ADDRESS         = 2
NETMASK             = 3
GATEWAY_IP_ADDRESS  = 4
RAC_DNSNAME         = 5

# Status codes

SSH_FAIL  = 0
PASS_FAIL = 1
CONNECT   = 2

# Regular expresions for a mac/ip address

MACREGEX = re.compile('([a-fA-F0-9]{2}[:|\-]?){6}')
IPREGEX  = re.compile('((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9])')

# Verbose mode

VERBOSE = False

# DRAC username

username = 'root'
# User

user = os.getlogin()

# Date

lastcheck = datetime.datetime.now().strftime('%Y%m%d%H%M')

# Some nasty colors

colours={"default":"",
         "blue":   "\x1b[01;34m",
         "cyan":   "\x1b[01;36m",
         "green":  "\x1b[01;32m",
         "red":    "\x1b[01;05;37;41m"}

# DRAC Password is read from file

f = open('dracpassword.txt')
password = (f.read()).strip()

def main():
    parser = argparse.ArgumentParser( prog = 'dracdumper.py', 
                                      description="""
                                      DRACDumper is a simple program to gather information
                                      from a Dell Remote Access Controller (DRAC)
                                                """, 
                                      conflict_handler='resolve')
    parser.add_argument('-m', '--getmacaddress', help='Get DRAC MAC Address.', action='store_true')
    parser.add_argument('-i', '--getipaddress', help='Get DRAC IP Address.', action='store_true')
    parser.add_argument('-n', '--getnetmask', help='Get DRAC Netmask Address.', action='store_true')
    parser.add_argument('-f', '--getfwversion', help='Get DRAC Firmware Version.', action='store_true')
    parser.add_argument('-r', '--getracdnsname', help='Get DRAC DNS Name.', action='store_true')
    parser.add_argument('-g', '--getgatewayip', help='Get DRAC Gateway IP.',action='store_true')
    parser.add_argument('-s', '--getsummary', help='Get DRAC Information Summary.',action='store_true')
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('DRAC', help='DRAC IP/Hostname.')
    args = parser.parse_args()
    # options  = vars(parser.parse_args())
    # print options
    if args.verbose:
        global VERBOSE 
        VERBOSE = True
    command = "racadm getsysinfo"
    output = ' '
    server = args.DRAC.rstrip()
    output = run_command(server, username, password, command)
    if output == ' ' :
        print "kk"
        show_banner(args.DRAC.rstrip(),SSH_FAIL)
        sys.exit(0)
    else:
        if args.getmacaddress:
            showdracinfo (output,server, MAC_ADDRESS)
        if args.getipaddress:
            showdracinfo (output,server, IP_ADDRESS)
        if args.getnetmask:
            showdracinfo(output,server, NETMASK)
        if args.getfwversion:
            showdracinfo (output,server, FIRMWARE_VERSION)
        if args.getracdnsname:
            showdracinfo (output,server, RAC_DNSNAME)
        if args.getgatewayip:
            showdracinfo (output,server, GATEWAY_IP_ADDRESS)
        if args.getsummary:
            summary()

def summary():
    pass
   # print 'summary!!'

# Run a command on the remote host
def run_command(server, username, password, command):
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(server, username=username, password=password, timeout=3)
        except (paramiko.SSHException, socket.error):
            if VERBOSE:
                show_banner(server,SSH_FAIL)
                return
            else:
                sys.exit("Unable to connect to %s, host is down/unreachable." %server)
                # Log to file
                # print "Failed to connect to %s." % server
                return
        stdin, stdout, stderr = ssh.exec_command(command)
	return stdout.readlines()
    except Exception:
        if VERBOSE:
            show_banner(server,PASS_FAIL)
            return
        else:
            sys.exit("Unable to connect to %s, bad password." %server) 
            # Log to file
            # print "Couldn't connect to %s" % (server)
            return

def showdracinfo(output,fqdn,request_type):
        drac = info2drac(fqdn, output)
        if VERBOSE:
            show_banner(fqdn,CONNECT)
        if request_type == FIRMWARE_VERSION:
            print drac[fqdn]['firmware']
        if request_type == IP_ADDRESS:
            print drac[fqdn]['ip']
        if request_type == MAC_ADDRESS:
            print drac[fqdn]['mac']
        if request_type == NETMASK:
            print drac[fqdn]['netmask']
        if request_type == GATEWAY_IP_ADDRESS:
            print drac[fqdn]['gateway']
        if request_type == RAC_DNSNAME:
            print drac[fqdn]['dnsrac']

def info2drac(fqdn, output):
       ip = gwip = dnsrac = mac = netmask = gwip = firmware = fwbuild = ' '
       for line in output:
            linearr = line.split('=')
            if len(linearr) > 1:
                first = linearr[0]
                last = linearr[1]
                if re.search('^Firmware Version', first):
                        firmware = last.strip()
		if re.search('^Firmware Build', first):
                        fwbuild = last.strip()
                        firmware = firmware+' ('+fwbuild+')'
                if re.search('^Current IP Address', first) and IPREGEX.search(last):
		        ip = last.strip()
                if re.search('^Current IP Netmask', first) and IPREGEX.search(last):
		        netmask = last.strip()
                if re.search('^Current IP Gateway', first) and IPREGEX.search(last):
		        gwip = last.strip()
                if re.search('^MAC Address', first) and MACREGEX.search(last):
                        mac = last.strip()
                if re.search('^DNS RAC Name', first):
		        dnsrac = last.strip()
                else:
                    pass
                    # Log to file
       drac = { fqdn : { 'ip' : ip, 'netmask' : netmask, 'mac' : mac, 'firmware' : firmware, 'gateway' : gwip, 'dnsrac' : dnsrac ,'password' : password }} 
       return drac

def show_banner(servername, status):
    banner = ''
    if status == SSH_FAIL:
        banner = "Couldn't connect to %s" % servername
        sys.stdout.write(colours["red"] + "+-----------------------" + str(banner) + "-----------------------+" + "\x1b[00m\n")
    elif status == PASS_FAIL:
        banner = "Failed to connect to %s. (Bad Password)" % servername
        sys.stdout.write(colours["red"] + "+-------------" + str(banner) + "--------------+" + "\x1b[00m\n")
    elif status == CONNECT:
        banner = "+----- Data for %s ----+" % servername
        sys.stdout.write(colours["green"] + "+-----------------------------------------------------------------------------------+" + "\x1b[00m\n")
        sys.stdout.write(colours["green"] + str(banner) + "\x1b[00m\n")
        sys.stdout.write(colours["green"] + "+-----------------------------------------------------------------------------------+" + "\x1b[00m\n")

if __name__ == "__main__":
    main()
